using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using Spring.Proxy;
using Spring.Util;

namespace Sedna.API.Remoting
{
    /// <summary>
    /// Generates client SAO proxy type. It wraps transparent proxy to enable use of Spring proxing capabilities.
    /// TODO: int: i'm not sure i did it right. Check and Test. Perhaps this should be done with IProxyMethodBuilder features
    /// </summary>
    public class SaoClientProxyTypeBuilder: SaoProxyTypeBuilder
    {

        protected override void ImplementInterface(TypeBuilder typeBuilder, IProxyMethodBuilder proxyMethodBuilder,
                                                   Type intf, Type targetType, bool proxyVirtualMethods)
        {
            IDictionary methodMap = new Hashtable();

            InterfaceMapping mapping = GetInterfaceMapping(targetType, intf);

            typeBuilder.AddInterfaceImplementation(intf);

            for (int i = 0; i < mapping.InterfaceMethods.Length; i++)
            {
                if (!proxyVirtualMethods &&
                    !mapping.TargetMethods[i].DeclaringType.IsInterface &&
                    mapping.TargetMethods[i].IsVirtual &&
                    !mapping.TargetMethods[i].IsFinal)
                    continue;

                MethodBuilder methodBuilder = proxyMethodBuilder.BuildProxyMethod(
                    mapping.InterfaceMethods[i], mapping.InterfaceMethods[i]); //the only change

                ApplyMethodAttributes(methodBuilder, mapping.TargetMethods[i]);

                methodMap[mapping.InterfaceMethods[i].Name] = methodBuilder;
            }
            foreach (PropertyInfo property in intf.GetProperties())
            {
                ImplementProperty(typeBuilder, intf, property, methodMap);
            }
            foreach (EventInfo evt in intf.GetEvents())
            {
                ImplementEvent(typeBuilder, intf, evt, methodMap);
            }
        }

/*
        /// <summary>
        /// Replacement for default implementation, which doesn't support transparent proxies.
        /// </summary>
		protected override void ImplementInterface(TypeBuilder builder, Type intf, Type targetType, bool explicitImplementation)
		{
			MethodInfo[] intfMethods = intf.GetMethods();

			builder.AddInterfaceImplementation(intf);

			IDictionary methodMap = new Hashtable();

			for (int i = 0; i < intfMethods.Length; i++)
			{
				MethodAttributes attributes = CalculateMethodAttributes(intfMethods[i]);
				string name;
				if (explicitImplementation)
				{
					name = intf.FullName + "." + intfMethods[i].Name;
					attributes |= MethodAttributes.Private;
				}
				else
				{
					name = intfMethods[i].Name;
					attributes |= MethodAttributes.Public;
				}
				MethodBuilder method = ImplementMethod(builder, name, attributes, intfMethods[i], intfMethods[i]);
				methodMap[intfMethods[i].Name] = method;
			}
			foreach (PropertyInfo property in intf.GetProperties())
			{
				ImplementProperty(builder, intf, property, methodMap);
			}
			foreach (EventInfo evt in intf.GetEvents())
			{
				ImplementEvent(builder, intf, evt, methodMap);
			}
		}        
*/
    }
}
